﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Configuration;

namespace TidyBlog.Data
{
    public abstract class DbProvider
    {
        /// <summary>
        /// CRUD命令文本模板
        /// </summary>
        protected readonly Dictionary<string, string> CmdTemplates;
        /// <summary>
        /// 类型映射
        /// </summary>
        protected Dictionary<Type, DbType> TypeMapping;
        /// <summary>
        /// WHERE子句运算符映射
        /// </summary>
        protected Dictionary<WhereOperator, string> WhereOperatorMap;


        public DbProvider()
        {
            ConnStr = ConfigurationManager.ConnectionStrings["TidyBlog"].ConnectionString;

            CmdTemplates = new Dictionary<string, string>();
            CmdTemplates.Add("CREATE", "INSERT INTO {0}({1}) VALUES({2})");
            CmdTemplates.Add("READ", "SELECT {1} FROM {0}{2}{3}");
            CmdTemplates.Add("READ_TOP_N", "SELECT {1} FROM {0}{2}{3}");
            CmdTemplates.Add("UPDATE", "UPDATE {0} SET {1}{2}");
            CmdTemplates.Add("DELETE", "DELETE FROM {0}{1}");
            CmdTemplates.Add("LAST_INSERT_ID", "SELECT @@IDENTITY");

            TypeMapping = new Dictionary<Type, DbType>();
            TypeMapping.Add(typeof(sbyte), DbType.SByte);
            TypeMapping.Add(typeof(short), DbType.Int16);
            TypeMapping.Add(typeof(int), DbType.Int32);
            TypeMapping.Add(typeof(long), DbType.Int64);
            TypeMapping.Add(typeof(byte), DbType.Byte);
            TypeMapping.Add(typeof(ushort), DbType.UInt16);
            TypeMapping.Add(typeof(uint), DbType.UInt32);
            TypeMapping.Add(typeof(ulong), DbType.UInt64);
            TypeMapping.Add(typeof(float), DbType.Single);
            TypeMapping.Add(typeof(decimal), DbType.Decimal);
            TypeMapping.Add(typeof(double), DbType.Double);
            TypeMapping.Add(typeof(string), DbType.String);
            TypeMapping.Add(typeof(bool), DbType.Boolean);
            TypeMapping.Add(typeof(DateTime), DbType.DateTime);

            WhereOperatorMap = new Dictionary<WhereOperator, string>();
            WhereOperatorMap.Add(WhereOperator.EQUAL, "=");
            WhereOperatorMap.Add(WhereOperator.NOT_EQUAL, "<>");
            WhereOperatorMap.Add(WhereOperator.GREATER, ">");
            WhereOperatorMap.Add(WhereOperator.GREATER_OR_EQUAL, ">=");
            WhereOperatorMap.Add(WhereOperator.LESS, "<");
            WhereOperatorMap.Add(WhereOperator.LESS_OR_EQUAL, "<=");
            WhereOperatorMap.Add(WhereOperator.BETWEEN, " BETWEEN ");
            WhereOperatorMap.Add(WhereOperator.LIKE, " LIKE ");
            WhereOperatorMap.Add(WhereOperator.IN, " IN ");
        }


        /// <summary>
        /// 获取数据库连接字符串
        /// </summary>
        public string ConnStr { get; protected set; }

        /// <summary>
        /// 获取DbProviderFactory实例
        /// </summary>
        public DbProviderFactory Factory { get; protected set; }

        /// <summary>
        /// 获取识别符的引用符
        /// </summary>
        public virtual string QuoteSymbol
        {
            get { return "[{0}]"; }
        }
        /// <summary>
        /// 获取参数前缀
        /// </summary>
        public virtual string ParamPrefix
        {
            get { return "@"; }
        }


        /// <summary>
        /// 获取命令模板
        /// </summary>
        /// <param name="name">命令名</param>
        /// <returns>命令模板</returns>
        public string GetCmdTemplate(string name)
        {
            return CmdTemplates[name];
        }

        /// <summary>
        /// 获取WHERE子句运算符对应的字符串表示
        /// </summary>
        /// <param name="oper">运算符</param>
        /// <returns>运算符对应的字符串表示</returns>
        public string GetWhereOperatorValue(WhereOperator oper)
        {
            return WhereOperatorMap[oper];
        }

        /// <summary>
        /// 获取某类型对应数据类型
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns>数据类型</returns>
        public DbType GetDbType(Type type)
        {
            return TypeMapping[type];
        }

        /// <summary>
        /// 创建分页辅助类
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <returns>分页辅助类</returns>
        public abstract PagingHelper<T> CreatePagingHelper<T>() where T : new();
    }


    /// <summary>
    /// WHERE字句逻辑运算符
    /// </summary>
    public enum LogicalOperator
    {
        /// <summary>
        /// 与运算符
        /// </summary>
        AND,
        /// <summary>
        /// 或运算符
        /// </summary>
        OR,
    }

    /// <summary>
    /// WHERE子句操作符
    /// </summary>
    public enum WhereOperator
    {
        /// <summary>
        /// 等于
        /// </summary>
        EQUAL,
        /// <summary>
        /// 不等于
        /// </summary>
        NOT_EQUAL,
        /// <summary>
        /// 大于
        /// </summary>
        GREATER,
        /// <summary>
        /// 小于
        /// </summary>
        LESS,
        /// <summary>
        /// 大于等于
        /// </summary>
        GREATER_OR_EQUAL,
        /// <summary>
        /// 小于等于
        /// </summary>
        LESS_OR_EQUAL,
        /// <summary>
        /// 在某个范围内
        /// </summary>
        BETWEEN,
        /// <summary>
        /// 搜索某种模式
        /// </summary>
        LIKE,
        /// <summary>
        /// 是某几个值
        /// </summary>
        IN
    }

    /// <summary>
    /// 排序方式
    /// </summary>
    public enum OrderWay
    {
        /// <summary>
        /// 升序
        /// </summary>
        ASC,
        /// <summary>
        /// 降序
        /// </summary>
        DESC
    }
}
